//
//  TextViewLinked.m
//  textviewLink
//
//  Created by dawid on 09-01-13.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "TextViewLinked.h"
#import "RegexKitLite.h"

typedef enum
	{	linkToURL = 0,		
		linkToTag = 1,	
		linkToUserDashboard = 2	,
		linkToMail = 3,
    linkToMap = 4
	} linkType;

@implementation TextViewLinked

+ (NSCursor *) fingerCursor;			// really should be in a category on NSCursor
{
    static NSCursor	*fingerCursor = nil;
	
    if (fingerCursor == nil)
    {
        fingerCursor = [[NSCursor alloc] initWithImage: [NSImage imageNamed: @"fingerCursor"]
											   hotSpot: NSMakePoint (0, 0)];
    }
	
    return fingerCursor;
}







#pragma mark PUBLIC INSTANCE METHODS -- NSView OVERRIDES

- (void) resetCursorRects
{
    NSAttributedString	*attrString;
    NSPoint				containerOrigin;
    NSRect				visRect;
    NSRange				visibleGlyphRange, visibleCharRange, attrsRange;
	
    //	Get the attributed text inside us
    attrString = [self textStorage];
	
    //	Figure what part of us is visible (we're typically inside a scrollview)
    containerOrigin = [self textContainerOrigin];
    visRect = NSOffsetRect ([self visibleRect], -containerOrigin.x, -containerOrigin.y);
	
    //	Figure the range of characters which is visible
    visibleGlyphRange = [[self layoutManager] glyphRangeForBoundingRect:visRect inTextContainer:[self textContainer]];
    visibleCharRange = [[self layoutManager] characterRangeForGlyphRange:visibleGlyphRange actualGlyphRange:NULL];
	
    //	Prime for the loop
    attrsRange = NSMakeRange (visibleCharRange.location, 0);
	
    //	Loop until we reach the end of the visible range of characters
    while (NSMaxRange(attrsRange) < NSMaxRange(visibleCharRange)) // find all visible URLs and set up cursor rects
    {
        NSString *linkObject;
		
        //	Find the next link inside the range
        linkObject = [attrString attribute: NSLinkAttributeName 
								   atIndex: NSMaxRange(attrsRange)
							effectiveRange: &attrsRange];
		
        if (linkObject != nil)
        {
            NSCursor		*cursor;
            NSRectArray		rects;
            unsigned int	rectCount, rectIndex;
            NSRect			oneRect;
			
            //	Figure what cursor to show over this link.
            cursor = [[self class] fingerCursor];
			
            //	Find the rectangles where this range falls. (We could use -boundingRectForGlyphRange:...,
            //	but that gives a single rectangle, which might be overly large when a link runs
            //	through more than one line.)
            rects = [[self layoutManager] rectArrayForCharacterRange: attrsRange
										withinSelectedCharacterRange: NSMakeRange (NSNotFound, 0)
													 inTextContainer: [self textContainer]
														   rectCount: &rectCount];
			
            //	For each rectangle, find its visible portion and ask for the cursor to appear
            //	when they're over that rectangle.
            for (rectIndex = 0; rectIndex < rectCount; rectIndex++)
            {
                oneRect = NSIntersectionRect (rects[rectIndex], [self visibleRect]);
                [self addCursorRect: oneRect  cursor: cursor];
            }
		}
    }
}

-(id)initWithFrame:(NSRect)frame{
	self = [super initWithFrame:frame];
	if (self){
		NSMutableDictionary* linkAttr = [NSMutableDictionary dictionaryWithDictionary:[self linkTextAttributes]];
		[linkAttr setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
		[self setLinkTextAttributes:linkAttr];
	}
	return self;
}

- (NSURL *) urlFromString: (NSString *) aString fromType:(linkType)urlType;
{
  aString = [aString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  NSURL	*url;
	NSString *path;
	switch ((linkType)urlType) {
		case linkToURL:
			    //url = [NSURL URLWithString: [NSString stringWithFormat:@"http://%@",aString]];
				url = [NSURL URLWithString: aString];
			break;
		case linkToTag:
			path = [NSString stringWithFormat:@"http://www.blip.pl/tags/%@", aString];
			url = [NSURL URLWithString:path];
			break;
		case linkToUserDashboard:
			path = [NSString stringWithFormat:@"http://www.blip.pl/users/%@/dashboard", aString];
			url = [NSURL URLWithString:path];

			break;
		case linkToMail:
			path = [NSString stringWithFormat:@"mailto:%@",aString];
			url  = [NSURL URLWithString:path];
			break;
    case linkToMap:
			path = [NSString stringWithFormat:@"http://maps.google.com/maps?q=%@", aString];
			url = [NSURL URLWithString:path];
			break;
		default:
			url = nil;
			break;
	}

	return url;
}
- (void) createLink
{

    NSURL				*linkURL;
    NSMutableDictionary		*linkAttributes;
	
	
	NSString *textString = [[[self string] copy] autorelease];
	@try{
    NSArray* matchedStrings = [textString arrayOfCaptureComponentsMatchedByRegex:@"((https?://)|(www\\.))(\\S*)" options:RKLCaseless|RKLDotAll|RKLMultiline range:NSMakeRange(0, [textString length]) error:NULL];
    for (NSArray* matches in matchedStrings) {
      NSRange matchRange = [textString rangeOfString:[matches objectAtIndex:0]];
      NSString* url = [NSString stringWithString:[matches objectAtIndex:0]];
      if (![url isMatchedByRegex:@"^https?://"]) {
        url = [NSString stringWithFormat:@"http://%@",url];
      }
      if ([[matches objectAtIndex:0] length]) {
  
        linkURL = [NSURL URLWithString:url];
        if (!linkURL)
          continue;
        
        linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
																	forKey: NSForegroundColorAttributeName];
				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
				//				[[self  textStorage] setAttributes:linkAttributes range:matchRange];
				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
      }
    }

    matchedStrings = [textString arrayOfCaptureComponentsMatchedByRegex:@"#([\\p{L}\\p{N}_-]+)" options:RKLMultiline|RKLDotAll range:NSMakeRange(0, [textString length]) error:NULL];
    for (NSArray* matches in matchedStrings) {
      NSRange matchRange = [textString rangeOfString:[matches objectAtIndex:0]];
      if ([[matches objectAtIndex:1] length]) {
        linkURL = [self urlFromString:[matches objectAtIndex:1] fromType:linkToTag];
        if (!linkURL)
          continue;
        linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
                                                            forKey: NSForegroundColorAttributeName];
				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
				//				[[self  textStorage] setAttributes:linkAttributes range:matchRange];
				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
      }
      
    };
    
    matchedStrings = [textString arrayOfCaptureComponentsMatchedByRegex:@"\\^([\\p{L}\\p{N}]+)" options:RKLCaseless|RKLDotAll|RKLMultiline range:NSMakeRange(0, [textString length]) error:NULL];
    for (NSArray* matches in matchedStrings) {
      NSRange matchRange = [textString rangeOfString:[matches objectAtIndex:0]];
      if ([[matches objectAtIndex:1] length]) {
        linkURL = [self urlFromString:[matches objectAtIndex:1] fromType:linkToUserDashboard];
        if (!linkURL)
          continue;
        
        linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
                                                            forKey: NSForegroundColorAttributeName];
				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
				//				[[self  textStorage] setAttributes:linkAttributes range:matchRange];
				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
      }
      
    };
    
    matchedStrings = [textString arrayOfCaptureComponentsMatchedByRegex:@"([\\S]+\\@([\\S])+\\.)([\\S]+)+"];
    for (NSArray* matches in matchedStrings) {
      NSRange matchRange = [textString rangeOfString:[matches objectAtIndex:0]];
      if ([[matches objectAtIndex:0] length]) {
        linkURL = [self urlFromString:[matches objectAtIndex:0] fromType:linkToMail];
        if (!linkURL)
          continue;
        
        linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
                                                            forKey: NSForegroundColorAttributeName];
				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
				//				[[self  textStorage] setAttributes:linkAttributes range:matchRange];
				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
      }
    };

    matchedStrings = [textString arrayOfCaptureComponentsMatchedByRegex:@"@/([\\p{L}\\p{N} ,_.-]+)/" options:RKLMultiline|RKLDotAll range:NSMakeRange(0, [textString length]) error:NULL];
    for (NSArray* matches in matchedStrings) {
      NSRange matchRange = [textString rangeOfString:[matches objectAtIndex:0]];
      linkURL = [self urlFromString:[matches objectAtIndex:1] fromType:linkToMap];
      if (linkURL) {
        linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
                                                            forKey: NSForegroundColorAttributeName];
				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
      };
    }
//		

//		//szukanie usera
//		matchedEnumerator = [textString matchEnumeratorWithRegex:[TextViewLinked regexUserDashboarType]];
//		while([matchedEnumerator nextRanges] != NULL) {
//			// Do something with the current match results of anEnumerator
//			NSRange matchRange = [matchedEnumerator currentRange];
//			matchedString =  [matchedEnumerator stringWithReferenceFormat:@"$1"];
//			if (matchedString){
//				linkURL =  [self urlFromString:matchedString
//									  fromType:linkToUserDashboard];
//				
//				if (!linkURL)
//					continue;
//				
//				linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
//																	forKey: NSForegroundColorAttributeName];
//				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
//				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
//				
//				//[[self  textStorage] setAttributes: linkAttributes  range: matchRange];
//				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
//			}
//		}
//		
//		//szukanie mail
//		matchedEnumerator = [textString matchEnumeratorWithRegex:[TextViewLinked regexMailType]];
//		while([matchedEnumerator nextRanges] != NULL) {
//			// Do something with the current match results of anEnumerator
//			NSRange matchRange = [matchedEnumerator currentRange];
//			matchedString =  [matchedEnumerator stringWithReferenceFormat:@"$0"];
//			if (matchedString){
//				linkURL =  [self urlFromString:matchedString
//									  fromType:linkToMail];
//				
//				if (!linkURL)
//					continue;
//				
//				linkAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor whiteColor]
//																	forKey: NSForegroundColorAttributeName];
//				[linkAttributes setObject: linkURL forKey: NSLinkAttributeName];
//				[linkAttributes setObject: [NSNumber numberWithBool: YES]  forKey: NSUnderlineStyleAttributeName];
//				
//				//[[self  textStorage] setAttributes: linkAttributes  range: matchRange];
//				[[self  textStorage] addAttributes: linkAttributes  range: matchRange];
//			}
//		}
	}
	@catch (NSException* ex) {
		@throw ex;
	}
}

#pragma mark statics
//+(id)regexWwwType
//{
//	static RKRegex *regex = nil;
//	if (!regex){
//		//regex = [RKRegex regexWithRegexString:@"(www\\.)([^\\s]+[\\.][a-zA-Z0-9]+)" options:RKCompileCaseless];
//		regex = [RKRegex regexWithRegexString:@"(www\\.)([\\S]+\\.)+([\\S]+\\/)+([\\S]+)?" options:RKCompileCaseless];
//	}
//	return regex;
//}
//+(id)regexHttpType
//{
//	static RKRegex *regex = nil;
//	if (!regex){
//		regex = [RKRegex regexWithRegexString:@"http://(www\\.)?([\\S]+\\.)+([\\S]+\\/)+([\\S]+)?" options:RKCompileCaseless];
//		//regex = [RKRegex regexWithRegexString:@"(http://)(www\\.)?([^\\s]+[a-zA-Z0-9])" options:RKCompileCaseless];
//	}
//	return regex;
//}
//+(id)regexTagType
//{
//	static RKRegex *regex = nil;
//	if (!regex){
//		regex = [RKRegex regexWithRegexString:@"#([^\\s\\.\\!\\?\\']+)" options:RKCompileCaseless|RKCompileUTF8];
//	//	regex = [RKRegex regexWithRegexString:@"#([a-zA-Z0-9ąęóżćńłśźĄĘÓŻĆŃŁŚŹ]+)" options:RKCompileCaseless|RKCompileUTF8];
////		regex = [RKRegex regexWithRegexString:@"#([\\w]+)" options:RKCompileCaseless|RKCompileUTF8];
//		//regex = [RKRegex regexWithRegexString:@"#(\\S+)" options:RKCompileCaseless|RKCompileUTF8| RKCompileNoUTF8Check];
//	}
//	return regex;
//}
//+(id)regexMailType
//{
//	static RKRegex *regex = nil;
//	if (!regex){
//		regex = [RKRegex regexWithRegexString:@"([\\S]+\\@([\\S])+\\.)([\\S]+)+" options:RKCompileCaseless];
//	}
//	return regex;
//}
//+(id)regexUserDashboarType
//{
//	static RKRegex *regex = nil;
//	if (!regex){
//		regex = [RKRegex regexWithRegexString:@"\\^([^\\s\\.]+)" options:RKCompileCaseless];
//	}
//	return regex;
//}
@end
